package com.suoluo.zenadmin.common.file;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.MemoryCacheImageInputStream;
import javax.swing.ImageIcon;

import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import com.sun.imageio.plugins.bmp.BMPImageReader;
import com.sun.imageio.plugins.gif.GIFImageReader;
import com.sun.imageio.plugins.jpeg.JPEGImageReader;
import com.sun.imageio.plugins.png.PNGImageReader;
import com.suoluo.zenadmin.common.StringUtil;

public final class ImageUtils {
	private ImageUtils() {

	}

	/**
	 * 等比压缩图片
	 * 
	 * @param inputFilePath
	 *            被压缩的图片文件路径
	 * @param outputFilepath
	 *            压缩后的图片文件路径
	 * @param height
	 *            压缩的高度
	 * @param width
	 *            压缩的宽度
	 */
	public static void compressImage(String inputFilePath,
			String outputFilepath, int height, int width) {
		File inputFile = new File(inputFilePath);
		File outFile = new File(outputFilepath);
		compressImage(inputFile, outFile, height, width, true);
	}
	
	/**
	 * 非等比压缩
	 * 
	 * @param inputFilePath
	 *            被压缩的图片文件路径
	 * @param outputFilepath
	 *            压缩后的图片文件路径
	 * @param height
	 *            压缩的高度
	 * @param width
	 *            压缩的宽度
	 */
	public static void forceCompressImage(String inputFilePath,
			String outputFilepath, int height, int width) {
		File inputFile = new File(inputFilePath);
		File outFile = new File(outputFilepath);
		compressImage(inputFile, outFile, height, width, false);
	}
	
	/**
	 * 等比压缩图片
	 * 
	 * @param inputFile
	 *            被压缩的图片
	 * @param outputFile
	 *            压缩后的图片
	 * @param height
	 *            压缩的高度
	 * @param width
	 *            压缩的宽度
	 */
	public static void compressImage(File inputFile,
			File outputFile, int height, int width) {
		compressImage(inputFile, outputFile, height, width, true);
	}
	
	/**
	 * 非等比压缩，直接根据定义的长，宽压缩
	 * 
	 * @param inputFile
	 *            被压缩的图片
	 * @param outputFile
	 *            压缩后的图片
	 * @param height
	 *            压缩的高度
	 * @param width
	 *            压缩的宽度
	 */
	public static void forceCompressImage(File inputFile,
			File outputFile, int height, int width) {
		compressImage(inputFile, outputFile, height, width, false);
	}
	
	
	private static void compressImage(Image img,File outputFile,int height, int width, boolean proportion){
		FileOutputStream out = null;
		try {
//			Image img = ImageIO.read(is);

			// 判断图片的格式是否正确
			if (img.getWidth(null) == -1) {
				throw new RuntimeException("invalid image type,outputFile="+outputFile.getAbsolutePath());
			}

			int newWidth = width;
			int newHeight = height;
			// 是否是等比缩放
			if (proportion) {
				// 为等比缩放计算输出的图片宽度及高度
				double widthRate = (img.getWidth(null))
						/ (double) width;
				double heightRate = (img.getHeight(null))
						/ (double) height;
				// 根据缩放比率大的进行缩放控制
				double rate = Math.min(widthRate, heightRate);
				newWidth = (int) ((img.getWidth(null)) / rate);
				newHeight = (int) ((img.getHeight(null)) / rate);
			}

			BufferedImage tag = new BufferedImage(newWidth, newHeight,
					BufferedImage.TYPE_INT_RGB);
			
			/*
			 * Image.SCALE_SMOOTH 的缩略算法 生成缩略图片的平滑度的 优先级比速度高 生成的图片质量比较好 但速度慢
			 */
			Graphics2D g = tag.createGraphics();
			g.drawImage(img.getScaledInstance(newWidth, newHeight,
					Image.SCALE_SMOOTH), 0, 0, null);
			g.dispose();
			File parentDir = outputFile.getParentFile();
			// 如果输出的目录不存在，则需要创建
			if (!parentDir.exists()) {
				parentDir.mkdirs();
			}
			out = new FileOutputStream(outputFile);
			// JPEGImageEncoder可适用于其他图片类型的转换
			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
			encoder.encode(tag);
		} catch (IOException e) {
			throw new RuntimeException(e);
		} finally {
			FileUtils.closeOutputStream(out);
		}
	}
	private static void compressImage(File inputFile, File outputFile,
			int height, int width, boolean proportion) {

		if (!inputFile.exists()) {
			throw new RuntimeException("file not exists,fileName="
					+ inputFile.getAbsolutePath());
		}
		try {
			compressImage(ImageIO.read(inputFile), outputFile, height, width, proportion);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	public static void compressImage(InputStream is, File outputFile,
			int height, int width){
		try {
			compressImage(ImageIO.read(is), outputFile, height, width, true);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	private static void compressImage(InputStream is, File outputFile,
			int height, int width, boolean proportion) {
		try {
			compressImage(ImageIO.read(is), outputFile, height, width, proportion);
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 直接压缩图片
	 * @param is
	 * @param outputFile
	 */
	public static void forceCompressImage(InputStream is, File outputFile,
			int height, int width){
		compressImage(is, outputFile, height, width,false);
	}
	
	/**
	 * 直接压缩图片
	 * @param is
	 * @param outputFile
	 */
	public static void forceCompressImage(InputStream is, String outputFile,
			int height, int width){
		compressImage(is, new File(outputFile), height, width,false);
	}

	/**
	 * 给图片添加水印
	 * 
	 * @param filePath
	 *            需要添加水印的图片的路径
	 * @param markContent
	 *            水印的文字
	 * @param markContentColor
	 *            水印文字的颜色
	 * @param qualNum
	 *            图片质量
	 * @return
	 */
	public static void createMark(String filePath, String markContent,
			Color markContentColor, float qualNum) {
		ImageIcon imgIcon = new ImageIcon(filePath);
		Image theImg = imgIcon.getImage();
		int width = theImg.getWidth(null);
		int height = theImg.getHeight(null);
		BufferedImage bimage = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);
		Graphics2D g = bimage.createGraphics();
		g.setColor(markContentColor);
		g.setBackground(Color.white);
		g.drawImage(theImg, 0, 0, null);
		// 添加水印的文字和设置水印文字出现的内容
		g.drawString(markContent, width / 5, height / 5);
		g.dispose();
		FileOutputStream out = null;
		try {
			out = new FileOutputStream(filePath);
			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
			JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bimage);
			param.setQuality(qualNum, true);
			encoder.encode(bimage, param);
			out.close();
		} catch (Exception e) {
			throw new RuntimeException("fail to createMakr,filePath" + filePath);
		} finally {
			FileUtils.closeOutputStream(out);
		}
	}

	/**
	 * 把图片印刷到图片上
	 * 
	 * @param pressImg
	 *            -- 水印文件
	 * @param targetImg
	 *            -- 目标文件
	 * @param x
	 *            --x坐标
	 * @param y
	 *            --y坐标
	 */
	public static void pressImage(String pressImg, String targetImg, int x,
			int y) {

		FileOutputStream out = null;
		try {
			// 目标文件
			File _file = new File(targetImg);
			Image src = ImageIO.read(_file);
			int wideth = src.getWidth(null);
			int height = src.getHeight(null);
			BufferedImage image = new BufferedImage(wideth, height,
					BufferedImage.TYPE_INT_RGB);
			Graphics g = image.createGraphics();
			g.drawImage(src, 0, 0, wideth, height, null);

			// 水印文件
			File _filebiao = new File(pressImg);
			Image src_biao = ImageIO.read(_filebiao);
			int wideth_biao = src_biao.getWidth(null);
			int height_biao = src_biao.getHeight(null);
			g.drawImage(src_biao, (wideth - wideth_biao) / 2,
					(height - height_biao) / 2, wideth_biao, height_biao, null);
			// 水印文件结束
			g.dispose();
			out = new FileOutputStream(targetImg);
			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
			encoder.encode(image);
		} catch (Exception e) {
			throw new RuntimeException("fail to press image,filePath"
					+ targetImg);
		}
		finally{
			FileUtils.closeOutputStream(out);
		}
	}

	/**
	 * 打印文字水印图片
	 * 
	 * @param pressText
	 *            --文字
	 * @param targetImg
	 *            -- 目标图片
	 * @param fontName
	 *            -- 字体名
	 * @param fontStyle
	 *            -- 字体样式
	 * @param color
	 *            -- 字体颜色
	 * @param fontSize
	 *            -- 字体大小
	 * @param x
	 *            -- 偏移量
	 * @param y
	 */

	public static void pressText(String pressText, String targetImg,
			String fontName, int fontStyle, int color, int fontSize, int x,
			int y) {
		FileOutputStream out = null;
		try {
			File _file = new File(targetImg);
			Image src = ImageIO.read(_file);
			int wideth = src.getWidth(null);
			int height = src.getHeight(null);
			BufferedImage image = new BufferedImage(wideth, height,
					BufferedImage.TYPE_INT_RGB);
			Graphics g = image.createGraphics();
			g.drawImage(src, 0, 0, wideth, height, null);
			// String s="www.qhd.com.cn";
			g.setColor(Color.RED);
			g.setFont(new Font(fontName, fontStyle, fontSize));

			g.drawString(pressText, wideth - fontSize - x, height - fontSize
					/ 2 - y);
			g.dispose();
			out = new FileOutputStream(targetImg);
			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
			encoder.encode(image);
			out.close();
		} catch (Exception e) {
			throw new RuntimeException("fail to press text,filePath"
					+ targetImg);
		}
		finally{
			FileUtils.closeOutputStream(out);
		}
	}
	
	/**
	 * 验证是否一个合法的格式的图像文件
	 * 支持格式[image/gif,image/jpeg,image/png]
	 * @param is
	 * @return
	 */
	public static boolean isValidImage(InputStream is) {
		String type = getImageType(is);
		return isValidImageType(type);
	}
	
	public static boolean isValidImageType(String type){
		if (StringUtil.isEmpty(type)){
			return false;
		}else{
			if ("image/gif".equals(type) || "image/jpeg".equals(type) || "image/png".equals(type)){
				return true;
			}else{
				return false;
			}
		}
	}
	
	public static String getImageType(File file) throws FileNotFoundException{
		InputStream is = null;
		try {
			is = new FileInputStream(file);
			return getImageType(is);
		} finally{
			FileUtils.closeIutputStream(is);
		}
	}
	
	public static String getImageType(InputStream is){
		MemoryCacheImageInputStream input = null;
		try {
			input = new MemoryCacheImageInputStream(is);
			Iterator<ImageReader> itr = ImageIO.getImageReaders(input);
			String type = null;
			while (itr.hasNext()) {
				ImageReader reader = itr.next();
				if (reader instanceof GIFImageReader) {
					type = "image/gif";
				} else if (reader instanceof JPEGImageReader) {
					type = "image/jpeg";
				} else if (reader instanceof PNGImageReader) {
					type = "image/png";
				} else if (reader instanceof BMPImageReader) {
					type = "application/x-bmp";
				}
			}
			return type;
		} finally {
			try {
				input.close();
			} catch (IOException e) {
				return null;
			}
		}
	}

	public static void main(String[] arg) {
		ImageUtils.compressImage("D:\\1.jpg", "D:\\mini1.jpg", 76, 164);
	}
}